#include "stdafx.h"
#include "TimeQueue.h"
#include <assert.h>

#define OPP_ADD 1
#define OPP_CHANGE 2
#define OPP_REMOVE 3

#define WACK_UNDEFIND 0
#define WACK_RESET 1
#define WACK_TIMEOUT 2

bool TimeQueue::proc(HANDLE handle)
{
	return size_t();
}

unsigned int __stdcall TimeQueue::workProc(void * param)
{
	// 创建完成事件对象

	HANDLE handle = CreateEvent(NULL, false, false, NULL);

	if (handle == NULL)
	{
		AfxMessageBox(GetLastError());

		return 1;
	}

	TimeQueue *timeQueue = reinterpret_cast<TimeQueue *>(param);

	int rec = 0;

	// 循环 处理事件对象 
	while (true)
	{
		if (WAIT_OBJECT_0 ==  WaitForSingleObject(timeQueue->systemWaitTimerObj, INFINITE))
		{
			if (!timeQueue->proc(handle))
			{
				//正常退出
				break;
			}
		}
		else
		{
			rec = 2;
		}
	}

	CloseHandle(handle);
	return rec;
}

TimeQueue::TimeQueue(unsigned int poolSize) :stopTimerQueue(false),
	timerList(NULL),
	timerAreAroused(0),
	systemWaitTimerObj(NULL),
	timerWorkThread(0),
	hTimer(true),
	poolSize(poolSize),
	operationQueue(NULL)
{
}


TimeQueue::~TimeQueue()
{
}

int TimeQueue::init()
{
	assert(this->systemWaitTimerObj == NULL);

	//创建一个可等待的计时器对象。

	/*
		ANDLE CreateWaitableTimer(
 		  LPSECURITY_ATTRIBUTES lpTimerAttributes, //安全描述符，可以为NULL        
 		  BOOL bManualReset, //是否为手动定时器，如果是手动的，需要调用SetWaitableTimer才能将定
		时器变成信号的，如果是自动的，则调用WaitForsingleObject即可实现定时器信号的重置 
 		  LPCTSTR lpTimerName //定时器名称，这对于进程间的定时器来说是有用的。
		);
		BOOL bManualReset:用于指明人工重置的定时器或自动重置的定时器。当发出人工重置的定时器信号
		通知时，等待该定时器的所有线程均变为可调度线程。当发出自动重置的定时器信号通知时，只有一
		个等待的线程变为可调度线程。
	*/
	if ((this->systemWaitTimerObj = CreateWaitableTimer(NULL, FALSE, NULL)) == NULL)
	{
		assert(0);

		return this->TQ_ERROR;
	}

	this->lockObj = new Lock();

	//分配定时器队列
	this->timerList = new timerDesList();

	if (this->poolSize > 0)
	{
		this->timerDesPoolSize = new timerDesc *[this->poolSize];
	}

	//创建工作线程
	if (0 == (this->timerWorkThread = _beginthreadex(NULL, 0, workProc, this, 0, NULL)))
	{
		assert(0);

		return this->TQ_ERROR;
	}

	this->operationQueue = new oppVector();

	this->stopTimerQueue = false;

	return this->T_SUCCESS;
}

/*
 创建定时器
 NO.1 超时时间
 NO.2 回调函数
 NO.3 参数
*/
TimeQueue::timer_t TimeQueue::createTimer(DWORD t, timerFunc callBack, void * param)
{
	/*
	* 把新创建的定时器按照超时的时间插入到合适的位置,要确保第一个定时器肯定是最先超时的定时器.
	*/
	this->lockObj->lockUp();

	timerDesc * timer = new timerDesc();

	timer->notice = callBack;

	timer->timeoutTime = this->hTimer.getNow() + this->hTimer.getCounter(t);

	timer->param = param;

	timer->watting = false;

	timer->status = 0;

	//定时器排队
	this->oppAcQuery(timer, OPP_ADD);

	this->lockObj->unLock();

	return timer;
}

void TimeQueue::oppAcQuery(timerDesc * timer, int oppType)
{
	//压入定时器
	this->operationQueue->push_back(std::pair< timerDesc *, int>(timer, oppType));

	//只有队头被移动后才能唤醒定时器
	bool isWackUp = false;

	if (OPP_ADD == oppType)
	{
		//添加的定时器比当前定时器，更快超时
		isWackUp = (currentTimer == NULL || currentTimer->timeoutTime > timer->timeoutTime);
	}
	else if (OPP_CHANGE == oppType)
	{
		//定时器被改变时，比当前定时器更快超时
		isWackUp = (currentTimer == timer || currentTimer->timeoutTime > timer->timeoutTime);
		
	}
	else
	{
		//当前定时器被删除或
		isWackUp = currentTimer == NULL || timer == currentTimer;
	}

	if (isWackUp)
	{
		//唤醒定时器
		this->wackUpTimer();
	}


}

void TimeQueue::wackUpTimer()
{

	if (WACK_RESET != this->timerAreAroused)
	{
		this->timerAreAroused = WACK_RESET;

		LARGE_INTEGER waitTimer;

		waitTimer.QuadPart = 2;

		//启动一个可等待计时器。将它设为未发信号状态 返回值 Long，非零表示成功，零表示失败
		/*
			BOOL SetWaitableTimer(
 			  HANDLE hTimer,                          // 定时器对象句柄
 			  const LARGE_INTEGER *pDueTime,          // 设定定时器从何时开始有信号
 			  LONG lPeriod,                           // 定时器周期
 			  PTIMERAPCROUTINE pfnCompletionRoutine,  // 回调函数
 			  LPVOID lpArgToCompletionRoutine,        // 传入回调函数参数
 			  BOOL fResume                          
			);
		*/
		if (!SetWaitableTimer(this->systemWaitTimerObj, &waitTimer, 0, NULL, NULL, false))
		{
			//错误
		}
	}
	else
	{
		//以手动触发
	}
}

//销毁队列
int TimeQueue::destory()
{

	//停止工作线程

	return 0;
}

int TimeQueue::deleteTimer(timer_t t, bool wait)
{
	timerDesc *timer = reinterpret_cast<timerDesc *>(t);


	//通知事件
	HANDLE handler = NULL;

	//加锁
	this->lockObj->lockUp();

	if (timer->status == 0)
	{
		this->oppAcQuery(timer, OPP_REMOVE);
	}

	if (wait)
	{
		timer->watting = wait;

		timer->autoDelete = true;

		if (wait)
		{
			handler = timer->notice;
		}
	}

	this->lockObj->unLock();

	if (handler == NULL)
	{
		//等待回调事件执行完毕
		WaitForSingleObject(handler, INFINITE);
	}

	return this->T_SUCCESS;
}
